/*
 * Copyright (C) 2011 Young,Fey <fey.young@gmail.com>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */

package com.youngfey.sqlite

import org.junit.*
import static org.junit.Assert.*
import java.util.zip.*
import static com.youngfey.sqlite.DataType.*
/**
 * 
 * @author Young,Fey <fey.young@gmail.com>
 */
class SQLiteTest {
    static huge = []
    static testdir = 'testdbs'

    @BeforeClass
    static void setUpClass() throws Exception {
        def folder = new File(testdir)
        clear folder
        folder.mkdir()
        // load tokens
        def file = new File('tokens.zip')
        def zi = new ZipInputStream(file.newInputStream())
        zi.nextEntry
        int len = 2048
        def bs
        def sb = new StringBuilder()
        int p = 0
        while(p != -1) {
            bs = new byte[len]
            p = zi.read(bs, 0, len)
            sb << new String(bs)
        }
        sb.toString().eachLine {
            def ts = it.split('\t')
            if(ts.size() == 2)
                huge << [token: ts[0], freq: ts[1]]
        }
        println huge.size()
    }

    @AfterClass
    static void tearDownClass() throws Exception {
        def folder = new File(testdir)
        clear folder
    }

    private static clear = { folder -> 
        if(folder.exists()) {
            folder.eachFile { it.delete() }
            folder.delete()
        }
    }

    @Test
    void testLoad() {
        def db = SQLite.load(new File('test.db'))
        def map = db.toMap()
        assert [all_types: [], column_test: [[id: 1, name: 'Hiarcs']],
        table_test: [[id: 1, name: 'Hiarcs', remarks: 12],
        [id: 2, name: 'Hiarcs2', remarks: 12.234],
        [id: 3, name: 'Hiarcs3', remarks: 'Hell']]], map
    }

    private createDB(name, tables = [], commit = false) {
        def dir = new File(testdir)
        def db = new File(dir, name)
        SQLite.create(db, tables, commit)
    }

    @Test
    void testCreate1() {
        def db = createDB('test_c.db')
        db.addTables([people(), books()])
        db.commit()
        db.addTable(pieces())
        db.commit()
        test(db)
    }

    @Test
    void testCreate2() {
        def db = createDB('test_c2.db', [people(), books()], true)
        db.addTable(pieces())
        db.commit()
        test(db)
    }

    private test = { db ->
        assertTrue db.hasTable('people')
        assertEquals 2, db.tables.people.columns.size()
        assertEquals 6, db.tables.people.size()
        assertEquals INTEGER, db.tables.book.columns.pages.type
        assertEquals TEXT, db.tables.book.columns.title.type
    }

    private people = { db = null ->
        def p = new Table('people', db,
        'CREATE TABLE people (id INTEGER PRIMARY KEY, name TEXT)')

        p.insertMaps([
            [id: 1, name: 'Hiarcs'],
            [name: 'Fritz'],
            [id: null],
            [name: 12],
            [name: 'Shredder', remarks: 'Deep Version'],
            [id: '14']
        ])
        p
    }

    private books = { 
        def b = new Table('book')
        b.insertMaps([
            [id: 1, title: 'My System', pages: 600],
            [title: "King's Gambit", pages: 512],
            [title: "Art of Chess", pages: 'MANY']
        ])
        b
    }

    private pieces = { 
        def p = new Table('pieces')
        p.insertMaps([
            [s: 'K', l: 'King'], [q: 'Queen']
        ])
        def c = new Column('s', true)
        println p.columns
        p.addColumn(c)
        p
    }

    @Test
    void testInsert() {
        def db = createDB('test_i.db', [people(), books()], true)
        db.tables.people.insertMaps([
            [name: 'Rybka', version: 4],
            [id: 219, name: 'Junior']
        ])
        db.commit()
        db.commit()
        assertEquals 8, db.tables.people.size()
        def db2 = SQLite.load(new File(testdir, 'test_i.db'))
        assertEquals 8, db2.tables.people.size()
    }

    @Test(timeout=50000L)
    void testHuge() {
        // insert 188000 rows
        // in 50s
        def db = SQLite.create(new File(testdir, 'huge.db'))
        def table = new Table('tokens', db, 
            'CREATE TABLE tokens (id INTEGER PRIMARY KEY, token TEXT, freq INTEGER)')
        db.addTable(table)
        table.insertMaps(huge)
        db.commit()
        assertEquals 188000, db.tables.tokens.size()
    }
}

